package kr.pe.asuraho.zhibogo;

import static kr.pe.asuraho.StaticMethods.createCookie;
import static kr.pe.asuraho.StaticMethods.decodeURL;
import static kr.pe.asuraho.StaticMethods.nvl;
import static kr.pe.asuraho.StaticMethods.parsingBoardDetail;
import static kr.pe.asuraho.StaticMethods.parsingBoardList;
import static kr.pe.asuraho.StaticMethods.parsingCookieInfo;
import static kr.pe.asuraho.StaticMethods.parsingMybogoLoginInfo;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import kr.pe.asuraho.DBConn;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;


public class ZAutoMain {
	
	public ZAutoMain() throws Exception{
		
		System.out.println(new Date());
		
		// 1. 로그파일 세팅
//		setLog("zAutoTorrent");
		
		// 2. 사용될 변수 초기화
		init();
		
		// 3. 사이트 로그인
		siteLogin();
		
		// 4. DB에서 다운받을 목록을 읽어온다.
		List<Map<String, String>> dataList = selectDataList();
		
		for(Map<String, String> data : dataList){
			
			Date startymd = sdf.parse(data.get("startymd"));
			Date maxDate = startymd;
			
			// 4.1 다운받을 내용을 하나씩 게시판에서 검색한다.
			get.setURI(new URI("/cdsb/board.php" + "?category=&board=" + data.get("board") + "&search=" + data.get("search") + "&keyword=" + URLEncoder.encode(data.get("keyword"), "utf-8")));
			html = client.execute(mybogo, get, responseHandler);
			List<Map<String, String>> boardList = parsingBoardList(html);
System.out.println("URL BoardList : " + URLDecoder.decode(get.getURI().toString(), "utf-8") );
			
			for(Map<String, String> board : boardList){
				Date writeDate = sdf.parse(board.get("date"));
				
				// 게시글 날짜 >= 다운시작 날짜
				if(writeDate.getTime() >= startymd.getTime()){
					
					// 4.2 이전에 받은 파일이라면 패스
					if(isDownloaded(board) > 0) continue;
					
					// 4.3 상세화면 조회(이전에 다운받지 않은 파일임)
					get.setURI(new URI("/cdsb/" + board.get("url")));
					html = client.execute(mybogo, get, responseHandler);
					List<Map<String, String>> detailList = parsingBoardDetail(html);
System.out.println("\tURL BoardDetail: " + get.getURI().toString());
					
					// 4.4 상세화면의 첨부파일 리스트
					for(Map<String, String> detail : detailList){
						
						String filename = "";
						if(detail.get("url").indexOf(".torrent") > 0){
							filename = detail.get("filename") + ".torrent";
						}else{
							filename = detail.get("filename");
						}
System.out.println("\t\tFile Download : " + filename);
						// 4.5 첨부파일 다운로드
						get.setURI(new URI(decodeURL(nvl(settingInfo.get("hibogo_url")), detail.get("url"))));
						
						// 4.6 다운로드한 첨부파일 저장
						attachDownload(client.execute(get), filename);
					}
					
					// 4.7 다운로드한 게시판 Title, Write Date 기록 (중복 다운로드 방지)
					insertTorDownload(board);
					
					// 
					if(writeDate.getTime() >= maxDate.getTime()){
						maxDate = writeDate;
					}
				}
			}
			
			// 4.8 키워드 테이블에 마지막 게시물의 write date로 수정
			updateTorKeyword(maxDate, data);
		}
		
		// 5. /Tdown 패스 변경
//		if("true".equals(prop.getProperty("is_server"))){
//			cmdExec("sudo chown -Rf torrent " + prop.getProperty("path_harddisk"));
//		}
	}
	
	
	/**
	 * 2. 사용될 변수 초기화
	 * @throws Exception 
	 */
	private void init() throws Exception {
		settingInfo = DBConn.getSqlSession().selectOne("kr.pe.asuraho.selectTorSetting");
		
		sdf = new SimpleDateFormat("yyyyMMdd");
		responseHandler = new BasicResponseHandler();
		
		hibogo = new HttpHost("www." + nvl(settingInfo.get("hibogo_url")), 80, "http");
		mybogo = new HttpHost("www.mybogo.net", 80, "http");
		cookieStore = new BasicCookieStore();
		client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();
		post = new HttpPost();
		get = new HttpGet();
	}
	
	/***
	 * 3. 사이트 로그인
	 * @throws Exception
	 */
	private void siteLogin() throws Exception {
		
		// 시작 세션 만들기
		cookieStore.addCookie(createCookie("startTime", String.valueOf(new Date().getTime())));
		
		// tobogo 로그인
		post.setURI(new URI("/cdsb/login_process.php"));
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("mode", "login"));
        nvps.add(new BasicNameValuePair("kinds", "outlogin"));
        nvps.add(new BasicNameValuePair("user_id", "asuraho"));
        nvps.add(new BasicNameValuePair("passwd", "cnwlgh"));
		post.setEntity(new UrlEncodedFormEntity(nvps));
		String html = client.execute(hibogo, post, responseHandler);
		
		// 로그인결과 HTML에서 cookie 정보 파싱 후 세팅
		Map<String, String> cookieData = parsingCookieInfo(html);
		cookieStore.addCookie(createCookie("MEMBER_ID", cookieData.get("MEMBER_ID") ));
		cookieStore.addCookie(createCookie("MEMBER_NAME", cookieData.get("MEMBER_NAME") ));
		cookieStore.addCookie(createCookie("MEMBER_EMAIL", cookieData.get("MEMBER_EMAIL") ));
		cookieStore.addCookie(createCookie("MEMBER_LEVEL", cookieData.get("MEMBER_LEVEL") ));
		cookieStore.addCookie(createCookie("MEMBER_NO", cookieData.get("MEMBER_NO") ));
		cookieStore.addCookie(createCookie("MEMBER_POINT", cookieData.get("MEMBER_POINT") ));
		cookieStore.addCookie(createCookie("MEMBER_SEX", cookieData.get("MEMBER_SEX") ));
		cookieStore.addCookie(createCookie("MEMBER_LOGIN_TIME", cookieData.get("MEMBER_LOGIN_TIME") ));
		cookieStore.addCookie(createCookie("LOGOUT", cookieData.get("LOGOUT") ));
		cookieStore.addCookie(createCookie("STR", cookieData.get("STR") ));
		cookieStore.addCookie(createCookie("STR1", cookieData.get("STR1") ));
		

		// 로그인결과 HTML에서 Mybogo 로그인 정보 추출
		Map<String, String> formData = parsingMybogoLoginInfo(html);
		
		// Mybogo 로그인
		post.setURI(new URI("/cdsb/login_process_extern.php"));
        nvps = new ArrayList<NameValuePair>();
        nvps.add(new BasicNameValuePair("MEMBER_ID", formData.get("MEMBER_ID")));
        nvps.add(new BasicNameValuePair("MEMBER_NAME", formData.get("MEMBER_NAME")));
        nvps.add(new BasicNameValuePair("MEMBER_EMAIL", formData.get("MEMBER_EMAIL")));
        nvps.add(new BasicNameValuePair("MEMBER_LEVEL", formData.get("MEMBER_LEVEL")));
        nvps.add(new BasicNameValuePair("MEMBER_NO", formData.get("MEMBER_NO")));
        nvps.add(new BasicNameValuePair("MEMBER_POINT", formData.get("MEMBER_POINT")));
        nvps.add(new BasicNameValuePair("MEMBER_PASS", formData.get("MEMBER_PASS")));
        nvps.add(new BasicNameValuePair("MEMBER_SEX", formData.get("MEMBER_SEX")));
        nvps.add(new BasicNameValuePair("MEMBER_LOGIN_TIME", formData.get("MEMBER_LOGIN_TIME")));
        nvps.add(new BasicNameValuePair("LOGOUT", formData.get("LOGOUT")));
        nvps.add(new BasicNameValuePair("STR", formData.get("STR")));
        nvps.add(new BasicNameValuePair("todo", formData.get("todo")));
		post.setEntity(new UrlEncodedFormEntity(nvps));
		html = client.execute(mybogo, post, responseHandler);
		
		// Mybogo 로그인결과  HTML에서 cookie정보 파싱 후 세팅
		// hibogo로그인후 쿠키세팅 하는데 mybogo 연결후 똑같은 쿠키 두번 세팅함 -- 이유는 해당 사이트가 개판이라서...
		cookieData = parsingCookieInfo(html);
		cookieStore.addCookie(createCookie("MEMBER_ID", cookieData.get("MEMBER_ID") ));
		cookieStore.addCookie(createCookie("MEMBER_NAME", cookieData.get("MEMBER_NAME") ));
		cookieStore.addCookie(createCookie("MEMBER_EMAIL", cookieData.get("MEMBER_EMAIL") ));
		cookieStore.addCookie(createCookie("MEMBER_LEVEL", cookieData.get("MEMBER_LEVEL") ));
		cookieStore.addCookie(createCookie("MEMBER_NO", cookieData.get("MEMBER_NO") ));
		cookieStore.addCookie(createCookie("MEMBER_POINT", cookieData.get("MEMBER_POINT") ));
		cookieStore.addCookie(createCookie("MEMBER_SEX", cookieData.get("MEMBER_SEX") ));
		cookieStore.addCookie(createCookie("MEMBER_LOGIN_TIME", cookieData.get("MEMBER_LOGIN_TIME") ));
		cookieStore.addCookie(createCookie("LOGOUT", cookieData.get("LOGOUT") ));
		cookieStore.addCookie(createCookie("STR", cookieData.get("STR") ));
		cookieStore.addCookie(createCookie("STR1", cookieData.get("STR1") ));
	}
	
	/***
	 * 4. DB에서 다운받을 목록을 읽어온다.
	 * @return
	 */
	private List<Map<String, String>> selectDataList() {
		return DBConn.getSqlSession().selectList("kr.pe.asuraho.selectTorKeywordDownloadList");
	}
	
	/***
	 * 4.2 이전에 받은 파일이라면 패스
	 * @param board
	 * @return
	 */
	private int isDownloaded(Map<String, String> board){
		return DBConn.getSqlSession().selectOne("kr.pe.asuraho.isDownloaded", board);
	}
	
	/***
	 * 4.6 다운로드한 첨부파일 저장
	 * @param response
	 * @param filename
	 * @throws Exception
	 */
	private void attachDownload(HttpResponse response, String filename) throws Exception{
		HttpEntity entity = response.getEntity();
		if (entity != null) {
			InputStream instream = entity.getContent();
			BufferedInputStream bis = null;
			BufferedOutputStream bos = null;
			
			String path = null;
			if(filename.indexOf(".torrent") > 0){
				path = nvl(settingInfo.get("torrent_file_path"));
			}else{
				path = nvl(settingInfo.get("smi_file_path"));
			}
			
			try {
				bis = new BufferedInputStream(instream);
				bos = new BufferedOutputStream(new FileOutputStream(new File(path + filename)));
				
				int inByte;
				while ((inByte = bis.read()) != -1) {
					bos.write(inByte);
				}

			} catch (Exception ex) {
				throw ex;
			} finally {
				if(bis != null) try{bis.close();}catch (Exception e) {}
				if(bos != null) try{bos.close();}catch (Exception e) {}
				if(instream != null) try{instream.close();}catch (Exception e) {}
			}
		}
	}
	
	/***
	 * 4.7 다운로드한 게시판 Title, Write Date 기록 (중복 다운로드 방지)
	 * @param board
	 * @throws Exception
	 */
	private void insertTorDownload(Map<String, String> board) throws Exception{
		DBConn.getSqlSession().insert("insertTorDownload", board);
		DBConn.getSqlSession().commit();
	}
	
	/***
	 * 4.8 키워드 테이블에 마지막 게시물의 write date로 수정
	 * @param maxDate
	 * @param data
	 * @throws Exception
	 */
	private void updateTorKeyword(Date maxDate, Map<String, String> data) throws Exception{
		data.put("maxDate", sdf.format(maxDate));
		DBConn.getSqlSession().update("kr.pe.asuraho.updateTorDownload", data);
		DBConn.getSqlSession().commit();
	}
	
	
	private SimpleDateFormat sdf = null;
	
	private ResponseHandler<String> responseHandler = null;
	private HttpHost hibogo = null;
	private HttpHost mybogo = null;
	private CookieStore cookieStore = null;
	private HttpClient client = null;
	private HttpPost post = null;
	private HttpGet get = null;
	
	private String html = null;
	private Map<String, Object> settingInfo = null; 
	
	public static void main(String[] args) throws Exception {
		new ZAutoMain();
	}
}